import java.util.HashMap;
import java.util.Map;

/**
 * @ClassName MyTest
 * @Author hj
 * @Description TODO
 * @Date 2024/6/18 10:57
 * @Version 1.0
 */

class TreeNode {
    int val;
    TreeNode left;
    TreeNode right;

    TreeNode(int val) {
        this.val = val;
    }
}

public class MyTest {
    public static int maxPoints(int[][] points) {
        if (points == null || points.length < 3) {
            return points == null ? 0 : points.length;
        }

        int maxCount = 0;
        for (int i = 0; i < points.length - 1; i++) {
            Map<String, Integer> linePoints = new HashMap<>();
            int duplicatePoints = 0;
            int currentMax = 0;

            for (int j = i + 1; j < points.length; j++) {
                if (points[i][0] == points[j][0] && points[i][1] == points[j][1]) {
                    duplicatePoints++;
                    continue;
                }

                int dx = points[j][0] - points[i][0];
                int dy = points[j][1] - points[i][1];

                // Check for vertical line
                if (dx == 0) {
                    linePoints.put("vertical", linePoints.getOrDefault("vertical", 0) + 1);
                } else {
                    // Calculate the slope as a fraction to avoid floating point issues
                    int gcd = gcd(Math.abs(dx), Math.abs(dy));
                    int slopeNumerator = dy / gcd;
                    int slopeDenominator = dx / gcd;
                    String slope = slopeNumerator + "/" + (slopeDenominator < 0 ? "-" : "") + Math.abs(slopeDenominator);

                    // Calculate the intercept (using the first point on the line)
                    int intercept = points[i][1] - slopeNumerator * points[i][0] / slopeDenominator;
                    String key = slope + ":" + intercept;
                    linePoints.put(key, linePoints.getOrDefault(key, 0) + 1);
                }

                currentMax = Math.max(currentMax, linePoints.get(lastKey(linePoints)) + 1);
            }

            // Add duplicate points to the max count
            maxCount = Math.max(maxCount, currentMax + duplicatePoints + 1);
        }

        return maxCount;
    }

    // Helper function to find the greatest common divisor (GCD)
    private static int gcd(int a, int b) {
        if (b == 0) {
            return a;
        }
        return gcd(b, a % b);
    }

    // Helper method to get the last key in a HashMap (note that this is not a standard method)
    // This is just for demonstration purposes, in practice you would avoid relying on this.
    private static String lastKey(Map<String, Integer> map) {
        String lastKey = null;
        for (String key : map.keySet()) {
            lastKey = key;
        }
        return lastKey;
    }

    public static void main(String[] args) {
        int[][] points = {{1,1},{3,2},{5,3},{4,1},{2,3},{1,4}};
        System.out.println(maxPoints(points)); // Output should be 4
    }
}
